﻿//#define XMLWRITER
//#define SERIALIZATION

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using SpicIE.Common;
using System.Windows.Forms;
using IEAccessibleTabs;
using System.IO;
using SHDocVw;
#if SERIALIZATION
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

#endif
using System.Xml.Serialization;
using System.Xml;



namespace TabSaver.SaveTabs
{
    /// <summary>
    /// This is a simple COM object wich implements the IOleCommandTarget.
    /// The interface is needed when a COM object shall be called via COM object invoke by another component.
    /// There are two needed interface member implementations which can be changed to match the demands of the user
    /// when the plugin is called.
    /// </summary>
    [ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDual),
    Guid(SaveTabsObject.PLUGIN_GUID),
    ProgId(SaveTabsObject.PLUGIN_PROGID)]
    public class SaveTabsObject : IOleCommandTarget
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        public const string PLUGIN_GUID = "87EBBA22-E898-4743-A2A8-08D760A087F9";
        public const string PLUGIN_PROGID = "TabSaver.SaveTabsObject";

        public SaveTabsObject()
        {
            // nothing needs to be done here, since this plugin shall only do 
            //something when invoked by another COM object via IOleCommandTarget::Exec
        }

        #region IOLECommandTarget interface implementation
        /// <summary>
        /// interface implementation for communicating with the ole object, in this case the menuitem as com object
        /// </summary>
        /// <param name="pguidCmdGroup"></param>
        /// <param name="cCmds"></param>
        /// <param name="prgCmds"></param>
        /// <param name="pCmdText"></param>
        /// <returns>-1</returns>
        public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
        {
            return -1;
        }



        /// <summary>
        /// interface implementation for firing the OLE Command event which can be subscribed in the intatiated class
        /// </summary>
        /// <param name="pguidCmdGroup"></param>
        /// <param name="nCmdID"></param>
        /// <param name="nCmdexecopt"></param>
        /// <param name="pvaIn"></param>
        /// <param name="pvaOut"></param>
        /// <returns>-1</returns>
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
#if SERIALIZATION
            Stream stream = null;

              List<string> test = new List<string>();
                test.Add("test");
                test.Add("test2");
                test.Add("test3");
                // Serialization
                XmlSerializer s = new XmlSerializer(typeof(List<string>));
                TextWriter w = new StreamWriter(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "IETabs" + Path.DirectorySeparatorChar + "quicktabs.tab");
                s.Serialize(w, test);
                w.Close();
#endif
#if XMLWRITER
            XmlTextWriter XMLWRITER = null;
#endif
            try
            {
                if (Directory.Exists(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "IETabs"))
                {
                }
                else
                {
                    Directory.CreateDirectory(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "IETabs");
                }
#if XMLWRITER
                XMLWRITER = new XmlTextWriter(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "IETabs" + Path.DirectorySeparatorChar + "quicktabs.tab", System.Text.Encoding.UTF8);
                XMLWRITER.Formatting = Formatting.Indented;
                XMLWRITER.WriteStartDocument(false);
                XMLWRITER.WriteComment("XML TABSAVER FILE");
#endif

                Guid IID_ITravelLogStg = new Guid("7EBFDD80-AD18-11d3-A4C5-00C04F72D6B8");
                Guid SID_STravelLogCursor = new Guid("7EBFDD80-AD18-11d3-A4C5-00C04F72D6B8");

                BrowserSession CurrentBrowserSession = new BrowserSession();

                foreach (InternetExplorer ie in IEAccessible.GetBrowserObjectsFromHandle(GetForegroundWindow()))
                {
                    TabSession CurrentTabSession = new TabSession();

                    IServiceProvider BrowserServiceProvider = ie as IServiceProvider;
                    int iHistoryCount = 0;
                    if (BrowserServiceProvider == null)
                    {
                        throw new Exception();
                    }

                    IntPtr TravelLogPointer = IntPtr.Zero;
                    int hr = BrowserServiceProvider.QueryService(ref SID_STravelLogCursor, ref IID_ITravelLogStg, out TravelLogPointer);

                    if ((TravelLogPointer == IntPtr.Zero) || (hr != 0)) //hr == 0 SUCCESS http://en.wikipedia.org/wiki/HRESULT
                    {
                        throw new Exception();
                    }

                    ITravelLogStg TravelLog = Marshal.GetObjectForIUnknown(TravelLogPointer) as ITravelLogStg;

                    if (TravelLog != null)
                    {
                        //Get the count
                        TravelLog.GetCount((int)TLMENUF.TLEF_ABSOLUTE, out iHistoryCount);
                        if (iHistoryCount == 0)
                        {
                            Debug.Print("\r\nNo history entries");
                        }

                        Debug.Print("\r\nCount =>" + iHistoryCount.ToString());

                        //Retrieve the TravelLogEnum and Iterate
                        IEnumTravelLogEntry TravelLogEnum = null;
                        TravelLog.EnumEntries((int)TLMENUF.TLEF_ABSOLUTE, out TravelLogEnum);
                        if (TravelLogEnum == null)
                        {
                            throw new Exception();
                        }
                        hr = 0;
                        ITravelLogEntry TravelLogEntry = null;
                        int fetched = 0;
                        IntPtr pTitle = IntPtr.Zero;
                        IntPtr pUrl = IntPtr.Zero;
                        const int MAX_FETCH_COUNT = 1; //An integer that specifies the number of items requested 

                        hr = TravelLogEnum.Next(MAX_FETCH_COUNT, out TravelLogEntry, out fetched);
                        Marshal.ThrowExceptionForHR(hr);
                        //while sucess, continue
                        for (int i = 0; 0 == hr; i++)
                        {
                            if (TravelLogEntry != null)
                            {
                                pTitle = IntPtr.Zero;
                                pUrl = IntPtr.Zero;
                                TravelLogEntry.GetTitle(out pTitle);
                                if (pTitle != IntPtr.Zero)
                                {
                                    Debug.Print("\r\nTitle =>" + Marshal.PtrToStringUni(pTitle));
                                }
                                TravelLogEntry.GetURL(out pUrl);
                                if (pUrl != IntPtr.Zero && pUrl != IntPtr.Zero)
                                {
                                    Debug.Print("\r\nUrl =>" + Marshal.PtrToStringUni(pUrl));
                                }

                                if ((pUrl != IntPtr.Zero) && (pUrl != IntPtr.Zero))
                                {
                                    CurrentTabSession.AddTravelLog(new TabSessionEntry(Marshal.PtrToStringUni(pUrl), Marshal.PtrToStringUni(pTitle)));
                                }


                                //tlstg.TravelTo(ptle);
                            }
                            hr = TravelLogEnum.Next(MAX_FETCH_COUNT, out TravelLogEntry, out fetched);
                            Marshal.ThrowExceptionForHR(hr);
                        }

                        #region Create new TravelLogEntry
                        ITravelLogEntry NewEntry;
                        int resultcreate = TravelLog.CreateEntry("http://www.almosen.de/", "Test", null, true, out NewEntry);
                        IntPtr crap;
                        NewEntry.GetURL(out crap);
                        Debug.Print(Marshal.PtrToStringUni(crap));
                        #endregion

                        TabSessionEntry CurrentSite = new TabSessionEntry(ie.LocationURL, ie.LocationName);
                        CurrentTabSession.AddTravelLog(CurrentSite);
                        Marshal.ReleaseComObject(TravelLogEnum);
                        Marshal.ReleaseComObject(TravelLog);
                    }

                    CurrentBrowserSession.AddTab(CurrentTabSession);
                    Console.Write("tet");
                }

#if SERIALIZATION
                #region fuck serialization
                stream = File.Open(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "IETabs" + Path.DirectorySeparatorChar + "quicktabs.tab", FileMode.Create);
                BinaryFormatter bFormatter = new BinaryFormatter();
                bFormatter.Binder = new Binder();
                bFormatter.Serialize(stream, CurrentBrowserSession);
                #endregion
#endif
                XmlSerializer s = new XmlSerializer(typeof(BrowserSession));
                TextWriter w = new StreamWriter(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "IETabs" + Path.DirectorySeparatorChar + "quicktabs.tab");
                s.Serialize(w, CurrentBrowserSession);
                w.Close();
#if XMLWRITER
                XMLWRITER.WriteStartElement("BrowserSession");
                foreach (TabSession TS in CurrentBrowserSession.SessionEntries)
                {
                    XMLWRITER.WriteStartElement("TabSession");
                    foreach (TabSessionEntry TSE in TS.TabTravelLogEntries)
                    {
                        XMLWRITER.WriteStartElement("TravelLog");
                        XMLWRITER.WriteElementString("URL", TSE.URL);
                        XMLWRITER.WriteElementString("Name", TSE.Name);
                        XMLWRITER.WriteEndElement();
                    }
                    XMLWRITER.WriteEndElement();
                }
                XMLWRITER.WriteEndElement();
                XMLWRITER.Flush();
#endif



                MessageBox.Show("Tabs Saved", "Tabs Saved", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
            finally
            {
#if SERIALIZATION
                if (stream != null)
                {
                    stream.Close();
                }
#endif
#if XMLWRITER
                if (XMLWRITER != null)
                {
                    XMLWRITER.Close();
                }
#endif
            }

            return -1;
        }
        #endregion
    }
}